import xml.dom.minidom
import os

class FlexClass:
    def __init__(self):
        self.current=""
        self.parent=""
        self.isContainer=False
        self.isAbstract=False
        self.methods=[]
        self.assertMethods=[]

class FlexMethod:
    def __init__(self):
        self.name="";
        self.args=[]
        self.argsType=[]

class ObjectGraphConstructor:
    def __init__(self):
        self.dom = xml.dom.minidom.parse("selenium-fx-automation-agent/src/SeleFxAgentEnv.xml")
        
    def construct(self):
            classes = []

            _containerMap = {}
            cinfos = self.dom.getElementsByTagName("ClassInfo")
            for cinfo in cinfos:
                    flexClass = FlexClass()
                    flexClass.current = cinfo.getAttribute("Name")
                    flexClass.parent=cinfo.getAttribute("Extends")
                    implClass = cinfo.getElementsByTagName("Implementation")[0].getAttribute("Class")
                    if implClass.find("Container") > -1:
                        flexClass.isContainer = True
                        _containerMap[flexClass.current]=""
                    else:
                        if _containerMap.has_key(flexClass.parent):
                            flexClass.isContainer = True
                            _containerMap[flexClass.current]=""
                       
                    
                    events = cinfo.getElementsByTagName("Events")
                    if events:
                            flexClass.methods = self.handleEvents(events[0].getElementsByTagName("Event"))

                    properties = cinfo.getElementsByTagName("Properties")
                    if properties:
                        flexClass.assertMethods = self.handleProperties(properties[0])
                        
                    classes.append(flexClass)
                    
            return classes

    def handleEvents(self, events):
            methods = []
            if events:
                    for event in events:
                            method = FlexMethod()
                            method.name = event.getAttribute("Name")
                            typeAndArg = self.handleEventProperties(event.getElementsByTagName("Property"))
                            method.argsType = typeAndArg[0]
                            method.args = typeAndArg[1]
                            method.codec = typeAndArg[2]
                            methods.append(method)
            return methods;


    def handleEventProperties(self, properties):
            methodArgType = []
            methodArg = []
            methodCodec = []
            if properties:
                    for property in properties:
                            methodArg.append(property.getAttribute("Name"))
                            type=property.getElementsByTagName("PropertyType")[0].getAttribute("Type")
                            methodArgType.append(type)
                            methodCodec.append(property.getElementsByTagName("PropertyType")[0].getAttribute("Codec"))
            return [methodArgType, methodArg, methodCodec]
        
    def handleProperties(self, properties):
            methods = []
            prop_list = properties.getElementsByTagName("Property");
            
            for property in prop_list:
                method = FlexMethod()
                method.name = property.getAttribute("Name")
                method.returnType = property.getElementsByTagName("PropertyType")[0].getAttribute("Type")
                methods.append(method)          
            return methods;
        
class Util:
    def convertFirstLetterUpper(self, value):
        return value[0].upper()+value.lstrip(value[0])    
           
if __name__ == "__main__":
    constructor = ObjectGraphConstructor()
    classes  = constructor.construct();

    util = Util()

    containerClazz=[]
    nonContainerClazz=[]
    
    for clazz in classes:
        if clazz.isContainer:
            containerClazz.append(clazz.current)
        else:
            nonContainerClazz.append(clazz.current)

        if clazz.current != "FlexDisplayObject":
            current = clazz.current.lstrip("Flex")
            parent = clazz.parent.lstrip("Flex")
            package = "org.thoughtworks.selenium.flex.ui";
            content = "package "+ package +"; \n"
            content = content + "import org.thoughtworks.selenium.flex.codec.*; \n"
            content = content + "import org.thoughtworks.selenium.flex.driver.*; \n"            

            content = content + "\n public class " + current + ((" extends " + parent) if clazz.parent else "")
            content = content + " { " + "\n"
            content = content + "\t private String automationClassName = \"" + clazz.current + "\"; \n"

            content = content + "\t protected " + current + "(DisplayObject parent, AutomationIdMap locator, FlexDriver driver) { \n"
            content = content + (("\t\t super(parent, locator, driver); \n" ) if clazz.parent else "")
            content = content + ("\t\t locator.put(\"automationClassName\", automationClassName); \n" )
            content = content + "\t } \n"
            
            content = content + "\t protected " + current + "(DisplayObject parent, String locator, FlexDriver driver) { \n"
            content = content + (("\t\t super(parent, locator, driver); \n" ) if clazz.parent else "")
            content = content + "\t } \n"

            for method in clazz.methods:
                content = content + "\t" + "public void " + method.name + "("
                argumentsWithType=""
                arguments=""
                for i in range(len(method.args)):
                    argumentsWithType = argumentsWithType + (method.argsType[i] if method.argsType[i] != "Enumeration" and method.codec[i] != "keyCode" else util.convertFirstLetterUpper(method.codec[i])) + " " + method.args[i] + (", " if i !=len(method.args)-1 else "")
                    arguments = arguments + method.args[i] + (", " if i !=len(method.args)-1 else "")
                content = content + argumentsWithType
                content = content + ") { \n "
                content = content + "\t driver.execute(new Command(\""+ method.name +"\""+ (("," + arguments) if arguments else "") + "), this); \n"
                content = content + "\t}" + "\n"
                
            for method in clazz.assertMethods:
                returnType = ""
                if method.returnType=="int":
                    returnType="Integer"
                elif  method.returnType=="Number":
                    returnType="Float"
                else:
                    returnType=method.returnType                
                content = content + "\t" + "public "+ returnType +" "+ method.name +"() throws Exception { \n "

                content = content + "\t return driver.execute("+returnType+".class, new Command(\""+ method.name +"\"), this); \n"
                content = content + "\t}" + "\n"                
            content = content + "}"
            fileName = "selenium-java-client-fx-driver/src/main/java/"+package.replace(".", "/")+"/"+current+".java"
            if os.path.exists(fileName):
                os.remove(fileName)
            f=open(fileName, 'w')
            f.write(content)
            
            


    """
    for clazzName in containerClazz:
        print "public "+ clazzName + " "+ clazzName + "() { }" + "\n"
        
    for clazzName in nonContainerClazz:
        print "public "+ clazzName + " "+ clazzName + "() { }" + "\n"        
    """
